/**
 * 布隆过滤器
 * 
 * @author shuyuan.dai 2018-11-05
 */
class BloomFilter {
    constructor(size, ruler) {
        size = Math.ceil(size * 9.6);
        const UNIT = 0x20;
        const SLIDER = 1 << (UNIT - 1);
        const seeds = [0x8639, 0x4ab1, 0x1421, 0x395b, 0x7e1, 0x805, 0x41a61];
        const hash = (data, seed) => {
            let hash = new Uint32Array(1);
            if (data.length > 0) {
                for (let i = 0; i < data.length; ++i) {
                    hash[0] = Math.abs(i * hash[0] + data[i].charCodeAt());
                }
            }
            hash[0] = hash[0] * seed;
            return hash[0] % size;
        };
        if (!(ruler instanceof Uint32Array)) {
            ruler = new Uint32Array(Math.ceil(size / UNIT));
        }

        Object.defineProperties(this, {
            add: {
                configurable: false,
                writable: false,
                value: (str) => {
                    for (let i=0; i < seeds.length; ++i) {
                        let code = hash(str, seeds[i]),
                        room = parseInt(code / UNIT),
                        unit = code % UNIT,
                        val = Math.abs(SLIDER >> unit);
                        ruler[room] |= val;
                    }
                }
            },
            has: {
                configurable: false,
                writable: false,
                value: (str) => {
                    for (let i=0; i < seeds.length; ++i) {
                        let code = hash(str, seeds[i]),
                        room = parseInt(code / UNIT),
                        unit = code % UNIT,
                        val = Math.abs(SLIDER >> unit);
                        if(!(ruler[room] & val)) 
                            return false;
                    }
                    return true;
                }
            },
            ruler: {
                configurable: false,
                get () {
                    return ruler;
                }
            }
        });
    }
}

exports.BloomFilter = BloomFilter;